package com.ww.java.generic.wildcard;

import java.util.Arrays;
import java.util.List;

public class CompilerIntelligence {

	@SuppressWarnings("unused")
	public static void main(String[] args) {
		List<? extends Fruit> flist = Arrays.asList(new Apple());
		Apple a = (Apple)flist.get(0);
		
		/**
		 * 对contains()和indexOf()的调用，这两个方法都接受Apple对象作为参数，而这些调用都可以正常执行。
		 * 这是意味着编译器实际上将检查代码，以查看是否有某个特定的方法修改了它的对象？
		 * 
		 * 通过查看ArrayList的文档，可以发现，编译器并没有这么聪明。尽管add()将接受一个具有泛型参数类型
		 * 的参数，但是contains()和indexOf()将接受Object类型的参数。因此当你指定一个ArrayList<? extends Fruit>时，
		 * add()参数就变成了"? extends Fruit"。从这个描述中，编译器并不能了解这里需要Fruit的哪个具体子类型，因此
		 * 它不会接受任何类型的Fruit。如果先将Apple向上转型为Fruit，也无关紧要——编译器将直接拒绝对参数列表中
		 * 涉及通配符的方法的调用（例如add()）。
		 * 
		 * 在使用contains()和indexOf()时，参数类型是Object，因此不涉及任何通配符，而编译器也将运行这个调用。
		 * 这意味着将由泛型类的设计者来决定哪些调用是”安全的“，并使用Object类型作为其参数类型。为了在类型中
		 * 使用了通配符的情况下禁止这类调用，我们需要再参数列表中使用类型参数。
		 */
		flist.contains(new Apple());
		flist.indexOf(new Apple());
	}
}
